﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using DataGenerator.DefaultSets;
using Dispatcher.Extensions;
using Dispatcher.LogicalModels;
using Dispatcher.ViewModels;
using Repository;

namespace Dispatcher.Views
{
    /// <summary>
    /// Interaction logic for PlaceTimetableView.xaml
    /// </summary>
    public partial class PlaceTimetableView
    {
        #region Fields

        /// <summary>
        /// Column Place Relation.
        /// </summary>
        private readonly Dictionary<DataGridColumn, Place> _places = new Dictionary<DataGridColumn, Place>();

        /// <summary>
        /// View model.
        /// </summary>
        private PlaceTimetableViewModel _viewModel;

        /// <summary>
        /// Current cell.
        /// </summary>
        private DataGridCell _currentCell;

        /// <summary>
        /// Date column.
        /// </summary>
        private DataGridTemplateColumn _dateColumn;

        /// <summary>
        /// Pair column.
        /// </summary>
        private DataGridTemplateColumn _pairColumn;

        /// <summary>
        /// Event Group Type Set.
        /// </summary>
        private readonly EventGroupTypeSet _eventGroupTypeSet;

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of the <see cref="PlaceTimetableView"/> class.
        /// </summary>
        public PlaceTimetableView()
        {
            InitializeComponent();
            EventInfo.IsEnabled = false;
            AdminToolsButton.Visibility = Visibility.Collapsed;
            _eventGroupTypeSet = new EventGroupTypeSet(MainWindow.Model.ModelContainer.EventGroupTypeSet);
        }

        #endregion

        #region Methods

        /// <summary>
        /// Generates the columns.
        /// </summary>
        /// <param name="personGroup">The person group.</param>
        public void GenerateColumns(PersonGroup personGroup)
        {
            _places.Clear();
            DataGrid.Columns.Clear();

            _dateColumn = new DataGridTemplateColumn
                              {
                                  Header = "Дата",
                                  CellTemplate = (DataTemplate)Resources["DateColumnTemplate"],
                                  IsReadOnly = true,
                              };

            _pairColumn = new DataGridTemplateColumn
                              {
                                  Header = "Пары",
                                  CellTemplate = (DataTemplate)Resources["PairColumnTemplate"],
                                  IsReadOnly = true,
                              };

            DataGrid.Columns.Add(_dateColumn);
            DataGrid.Columns.Add(_pairColumn);

            foreach (var place in personGroup.Place)
            {
                var column = new DataGridTemplateColumn
                                 {
                                     CellTemplate = (DataTemplate)Resources["ColumnTemplate"],
                                     IsReadOnly = true,
                                     Header = "Аудитория " + place.Name,
                                 };

                DataGrid.Columns.Add(column);
                _places.Add(column, place);
            }
        }

        /// <summary>
        /// Loads the data.
        /// </summary>
        public void LoadData()
        {
            Calendar1.SelectedDate = _viewModel.FromDate;
            Calendar1.DisplayDate = _viewModel.FromDate;
            _viewModel.LoadData();
            DataGrid.Items.Clear();
            foreach (var dailyEvents in _viewModel.Timetable)
            {
                DataGrid.Items.Add(dailyEvents);
            }
        }

        /// <summary>
        /// Handles the ScrollChanged event of the DataGrid control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Controls.ScrollChangedEventArgs"/> instance containing the event data.</param>
        private void DataGrid_ScrollChanged(object sender, ScrollChangedEventArgs e)
        {
            var cells = DataGrid.GetVisibleCells();

            foreach (var cell in cells)
            {
                var dayTable = cell.DataContext as DailyEvents;
                if (dayTable == null)
                {
                    continue;
                }

                if (cell.Column == _pairColumn)
                {
                    cell.DataContext = PlaceTimetableViewModel.StandartPairs;
                }

                if (_places.ContainsKey(cell.Column))
                {
                    var place = _places[cell.Column];
                    cell.DataContext = dayTable.Events[place];
                }
            }
        }

        /// <summary>
        /// Handles the DataContextChanged event of the UserControl control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.DependencyPropertyChangedEventArgs"/> instance containing the event data.</param>
        private void UserControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            _viewModel = (PlaceTimetableViewModel)e.NewValue;
            LoadData();
            GenerateColumns(_viewModel.PersonGroup);

            MainWindow.CurrentUser =
                _viewModel.ModelContainer.UserSet.FirstOrDefault(u => u.Role.Name == "Administrator");
        }

        /// <summary>
        /// Handles the Click event of the NextWeekButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void NextWeekButton_Click(object sender, RoutedEventArgs e)
        {
            _viewModel.FromDate = _viewModel.FromDate.AddDays(+7);
            _viewModel.ToDate = _viewModel.FromDate.AddDays(6);
            LoadData();
        }

        /// <summary>
        /// Handles the Click event of the PrevWeekButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void PrevWeekButton_Click(object sender, RoutedEventArgs e)
        {
            _viewModel.FromDate = _viewModel.FromDate.AddDays(-7);
            _viewModel.ToDate = _viewModel.FromDate.AddDays(5);
            GenerateColumns(_viewModel.PersonGroup);
            LoadData();
        }

        /// <summary>
        /// Handles the Click event of the ReserveButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ReserveButton_Click(object sender, RoutedEventArgs e)
        {
            var ev = EventInfo.DataContext as Event;
            if (ev == null)
            {
                return;
            }

            if (ev.Id == 0)
            {
                var view = new EventEditControl { Owner = Application.Current.MainWindow, Title = _places[_currentCell.Column].Name };
                var viewModel = new EventEditViewModel(_viewModel.ModelContainer, ev.StartTime.TimeOfDay, ev.EndTime.TimeOfDay)
                {
                    Name = "Новое событие",
                    SingleDate = ev.StartTime.Date,
                    Place = _places[_currentCell.Column],
                };

                viewModel.Bind(view);

                if (view.ShowDialog() == true)
                {
                    LoadData();
                }
            }

            if (ev.Id > 0)
            {
                ev.EventGroup.Load();
                if (MainWindow.CurrentUser == null || MainWindow.CurrentUser.Role.Name == "User")
                {
                    if (MainWindow.CurrentUser == null || ev.OrganizePersonGroup == null ||
                        ev.OrganizePersonGroup.Person.FirstOrDefault() != MainWindow.CurrentUser.Person)
                    {
                        MessageBox.Show("Нельзя отменять чужие события");
                        return;
                    }
                }
              
                var bindedEventGroup =
                    ev.EventGroup.FirstOrDefault(g => g.EventGroupType.Id == _eventGroupTypeSet.GroupByPeriod.Id);

                var result = MessageBox.Show("Удалить связанные переодические события вместе с текущим?", "Удаление", MessageBoxButton.YesNoCancel);
                if (result == MessageBoxResult.Cancel)
                {
                    return;
                }

                if (bindedEventGroup != null && result == MessageBoxResult.Yes)
                {
                    var events = bindedEventGroup.Event.ToList();
                    foreach (var bindedEvent in events)
                    {
                        bindedEvent.EventGroup.Clear();
                        _viewModel.ModelContainer.DeleteObject(bindedEvent);
                    }

                    _viewModel.ModelContainer.EventGroupSet.DeleteObject(bindedEventGroup);
                }
                else
                {
                    _viewModel.ModelContainer.DeleteObject(ev);
                }

                _viewModel.ModelContainer.SaveChanges();
                LoadData();
            }
        }

        /// <summary>
        /// Handles the Click event of the LoginButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void LoginButton_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new LoginWindow();
            if (dialog.ShowDialog() == true)
            {
                LoginButton.Visibility = Visibility.Collapsed;
                EventInfo.IsEnabled = true;
                UserName.Text = MainWindow.CurrentUser.Name;
                UserName.Visibility = Visibility.Visible;

                if (MainWindow.CurrentUser.Role.Name == "Administrator")
                {
                    AdminToolsButton.Visibility = Visibility.Visible;
                }
            }
            else
            {
                MainWindow.CurrentUser = null;
            }
        }

        /// <summary>
        /// Changes the event.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void ChangeEvent(object sender, RoutedEventArgs e)
        {
            var element = (FrameworkElement)e.OriginalSource;
            var ev = element.DataContext;
            var cell = element.GetNearestVisualParent<DataGridCell>();

            if (ev is Event)
            {
                EventInfo.DataContext = ev;
                _currentCell = cell;
            }
        }

        /// <summary>
        /// Handles the Click event of the AdminToolsButton control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.RoutedEventArgs"/> instance containing the event data.</param>
        private void AdminToolsButton_Click(object sender, RoutedEventArgs e)
        {
            var view = new AdminToolsView();
            MainWindow.Model.Documents.Add(view);
            var viewModel = new EntityListViewModel<User>(MainWindow.Model.ModelContainer);
            viewModel.Bind(view);
            view.Show();
            view.Activate();
        }

        private void ReserveButton_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
        {
           var ev = EventInfo.DataContext as Event;
            if (ev == null)
            {
                return;
            }

            if (ev.Id == 0)
            {
                var view = new EventEditControl { Owner = Application.Current.MainWindow, Title = _places[_currentCell.Column].Name };
                var viewModel = new EventEditViewModel(_viewModel.ModelContainer, ev.StartTime.TimeOfDay, ev.EndTime.TimeOfDay)
                                    {
                                        Name = "Новое событие",
                                        SingleDate = ev.StartTime.Date,
                                        Place = _places[_currentCell.Column],
                                    };

                viewModel.Bind(view);

                if (view.ShowDialog() == true)
                {
                    LoadData();
                }
            }
        }

        private void FocusButton(object sender, MouseButtonEventArgs e)
        {
            ((Button)sender).Focus();
            ChangeEvent(sender, e);
        }

        private void Calendar1_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)
        {
            _viewModel.FromDate = (DateTime) Calendar1.SelectedDate;
            _viewModel.ToDate = _viewModel.FromDate.AddDays(6);
            LoadData();
        }

        #endregion
    }
}
